package com.cherish.meeting.common.http;

import com.cherish.meeting.common.util.StringUtil;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;

import org.apache.http.config.Registry;

import org.apache.http.config.RegistryBuilder;

import org.apache.http.conn.socket.ConnectionSocketFactory;

import org.apache.http.conn.socket.PlainConnectionSocketFactory;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClientBuilder;

import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.ssl.SSLContextBuilder;

import org.apache.http.ssl.TrustStrategy;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;

import java.security.KeyManagementException;

import java.security.KeyStoreException;

import java.security.NoSuchAlgorithmException;

import java.security.cert.X509Certificate;

/**
 * @author: wuhong-016
 * @time: 2021/3/11 16:51
 * @version: v1.0.0
 * @description:TODO
 */
@Configuration
public class HttpClientConfig {

    @Value("${http.maxTotal}")
    private Integer maxTotal;//最大连接数

    @Value("${http.defaultMaxPerRoute}")
    private Integer defaultMaxPerRoute;//支持并发数

    @Value("${http.connectTimeout}")
    private Integer connectTimeout;//连接的超时时间

    @Value("${http.connectionRequestTimeout}")
    private Integer connectionRequestTimeout;//从连接池获取连接的超时时间

    @Value("${http.socketTimeout}")
    private Integer socketTimeout;//数据传输超时时间

    @Value("${http.staleConnectionCheckEnabled}")
    private boolean staleConnectionCheckEnabled;//提交请求前测试连接是否可用

    @Value("${http.proxy}")
    private String proxy;//代理服务器

    private static SSLContext sslContext = null;

    static {
        try {
            sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有
                @Override
                public boolean isTrusted(X509Certificate[] xcs, String string) {
                    return true;
                }
            }).build();
        } catch (KeyStoreException ex) {
            ex.printStackTrace();
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        } catch (KeyManagementException ex) {
            ex.printStackTrace();
        }
    }


    /**
     * 实例化一个连接池管理器,并且设置最大连接数，支持并发数
     *
     * @return
     */
    @Bean(name = "httpClientConnectionManager")
    public PoolingHttpClientConnectionManager getHttpClientConnectionManager() {
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER))
                .build();
        PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        httpClientConnectionManager.setMaxTotal(maxTotal);
        httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
        return httpClientConnectionManager;

    }

    /**
     * 实例化连接池，设置连接池管理器。
     * <p>
     * 这里需要以参数形式注入上面实例化的连接池管理器
     *
     * @param httpClientConnectionManager
     * @return
     */
    @Bean(name = "httpClientBuilder")
    public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager httpClientConnectionManager) {
        HttpClientBuilder builder = HttpClientBuilder.create();

        RequestConfig.Builder requestConfig = RequestConfig.custom();
        if (StringUtil.isNotEmpty(proxy)) {
            HttpHost httpProxy = HttpHost.create(proxy);
            requestConfig.setProxy(httpProxy);
        }
        builder.setConnectionManager(httpClientConnectionManager);
        return builder;
    }


    /**
     * 注入连接池，用于获取httpClient
     *
     * @param httpClientBuilder
     * @return
     */
    @Bean
    public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder) {
        CloseableHttpClient httpClient = httpClientBuilder.build();
        return httpClient;
    }


    /**
     * Builder是RequestConfig的一个内部类
     * <p>
     * 通过RequestConfig的custom方法来获取到一个Builder对象
     * <p>
     * 设置builder的连接信息
     * <p>
     * 这里还可以设置proxy，cookieSpec等属性。有需要的话可以在此设置
     *
     * @return
     */
    @Bean(name = "builder")
    public RequestConfig.Builder getBuilder() {
        RequestConfig.Builder builder = RequestConfig.custom();
        return builder.setConnectTimeout(connectTimeout).
                setConnectionRequestTimeout(connectionRequestTimeout).
                setSocketTimeout(socketTimeout);
    }


    /**
     * 使用builder创建一个RequestConfig对象
     *
     * @param builder
     * @return
     */
    @Bean
    public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder) {
        RequestConfig requestConfig = builder.build();

        return requestConfig;

    }

}